#build update 0.1.3
Explore tagged Tumblr posts
Text
Lancer Tactics update (0.1.3)
New build is up! Changelog is here, along with some behind-the-scenes pics of the soundtrack being created.
176 notes
·
View notes
Text
LCP 0.1.3 (Draft of the Hannibal and Yeti licenses and some much needed wing clipping)
Major Updates:
completed the current drafts for the HA Hannibal and the HORUS Yeti.
HA Hannibal: The Hannibal is an artillery mech that is capable of permanently breaking armour off frozen enemies,
HORUS Yeti: The Yeti is a support mech with a wide range of systems to reduce Heat from allies.
Content Changes: I've altered some existing content after some build testing on my side and some feedback I noticed in Pilotnet.
Toad License Omni-Propulsion Gear: Changed it to instead let you move any of your Drones to move 1d3 spaces in normal environments and 1d6 in zero-G or underwater.
Salamander License Napalm Launcher: Changed the range to 10 and the damage to be 1d3+1 Burn. Also added an effect from attacking to deal 1 heat to anyone adjacent to the attacker, including the attacker themselves, if they fail an Engineering save.
Wasp License Venom Sting: Added the requirement for enemies to make a systems save before you apply an invade option.
Wasp Mech:Base Stats: E-Defense down from 8 to 6, Sensor Range down from 10 to 3, Target save up from 11 to 12, Speed down from 8 to 5 Traits: Nanoweave wings has been changed from the Wasp always Hovering to instead need to use a quick action to start Hovering and gain +2 speed. Mechanosensory Escape Planning has been changed to be that the Wasp does trigger overwatch but instead counts as Invisible instead of flat immunity. Fragile has been renamed Fragile Wings and now has the added effect that when the Wasp loses structure it must stabilise before it can use it's Nanoweave wings trait.
Core Bonuses: Overclocked Motors: In order to take Overclocked Motors you must now have 7 or less speed and you are only able to move 5 spaces with boost.
The next update will likely be after I have had art of the Hannibal and Yeti commissioned and will also contain the draft compendium descriptions for the Hannibal and Yeti. Thank you for all your support so far and I hope you all enjoy what you have seen so far. Even if some of it is balanced by someone who really should stop doing only night work.
2 notes
·
View notes
Video
youtube
If you don't feel like watching that then read below the cut. (it's mostly the same words):
The Tinkerer!
First things first, this update adds a new player class to the game;
The Tinkerer
. Tinkerers are crafty item-users, planners, and mechanics, and as such they are associated with
Intelligence
. Their class ability isn't really an ability so much as a companion: All tinkerers have a flying robot buddy that can carry items and fight alongside them.
The Tinker-Bot has four different modes that the player can switch between at will:
In Defensive mode, the tinker-bot will only attack enemies that you're already in combat with, but won't fly off and start fights on its own.
In Offensive mode, it'll attack any nearby creature regardless of whether they're aware of you or not.
In Manual mode, you control the robot directly, letting you move, attack, and pick up items with it, but you lose control of your Kid while doing so.
In Idle mode, the tinker-bot enters an inactive standby state: You can use this mode to tell the bot to wait somewhere out of the way while you go do something dangerous. You can also interact with the tinkerbot in this mode to manage its held item or modify its behaviour.
Of course, nothing lives forever, and the tinker-bot will be destroyed if it takes too much damage. When this happens it breaks into three pieces that are scattered around the level, and in order to restore it you'll need to reassemble the parts and then take a moment to power it up again. When you repair your bot this way, you'll become mentally exhausted for a couple floors, during which time if it breaks again, repairing it might result in some...lower quality results - or else come at a high cost.
In addition to their tinker-bot companions, Tinkerers also have a chance to start with items unique to their class, called "Contraptions." There are only two kinds of contraptions so far - Grenades and Wind-up Turtles - but more are planned for future updates.
Those are the essentials of the new Tinkerer class, but there's much more to them that you'll have to discover for yourself. I'm excited to finally have the fourth class implemented and I think they'll find their place alongside the bully, wanderer, and poet as a valued addition to the game.
Catacoins
The next major addition to this update is the introduction of Catacoins. These coins are a kind of currency that you gain over the course of multiple runs by getting far and gaining reputations. Different reputations are worth different amounts of Catacoins based on how difficult they are to get, but even if you don't get any reputations at all, you'll still slowly gain Catacoins over the course of your runs to spend.
As for what you do with these coins, there's only one thing to spend them on so far, but I think it's pretty neat: You can spend coins to customize the otherwise randomly-rolled Kids, tweaking certain starting traits and equipment to create a kid that suits the way you play, but keep in mind that the more specific you are, the pricier the kid becomes.
You can choose to spend just a few coins for a simple quality of life improvement, or save them up to roll an expensive all-star suited to your tastes -- but play well, to make sure they survive and make the investment worthwhile.
Shops
I've also made some changes to shopkeepers: They're no longer generic sellers-of-all things, but are instead divided into four different shop types: blacksmiths, magic dealers, potion brewers, and clothiers. In addition to each shop type offering different kinds of items, shopkeepers themselves now offers a service unique to their profession.
Blacksmiths can improve your weapon's stats and repair damaged equipment.
Magic dealers will sell you a single spell that doesn't require learning points to acquire.
Potion brewers will identify any potion type, for a price.
Clothiers offer enchantments for your armor and shoes.
What's Next?
So, now that this new class is out and the groundwork has been laid for meta progression in the form of Catacoins, my next major goals are the implementation of the third environment, the Deep Dark and the addition of Tier 3 boons, and transitioning development to Game Maker Studio 2. But like, in the reverse order from what I just said. Of course this all will be aalongside the continued fleshing-out of existing systems - adding more meals and meal effects, more things to purchase with catacoins, more spell overloads and trances, etc.
I'm Still Not Dead
Lastly, as I've mentioned before but will continue to mention for as long as it remains true: If you ever think I'm dead or have dropped off the face of the earth (like I know sometimes happens) Check out http://twitch.tv/fourbitfriday on Mondays or Fridays - unless I'm out of town I'll always be dev-streaming from 3-6PM PST. We've also got a relatively active discord channel that y'all're all welcome to come in and chat ‘bout stuff.
So anyway, sorry this build took such a long time getting out - there were a lot of irritating and common bugs in the last version, and going so long without at least addressing them was pretty unacceptable of me. My bad. I'll try to do better forever. After all, what can we do but strive evermore for betterment - of ourselves, of the world around us - or else be crushed by the sameness and the worseness of all prior existence; softly smothered by the enticing and outstretched arms of the grand beast named Contentment with Mediocrity.
So you strive, stumbling at times, sure, but resisting that beastly embrace. And so shall I strive too - until I am Better. Until I am Best. And even further, until the infinite endeavors which lie beyond.
#update#build update 0.1.3#devlog#catacomb kids#roquelike#platformer#someone come calm me down please
17 notes
·
View notes
Photo
A Beginner’s Guide to npm, the Node Package Manager
Node.js makes it possible to write applications in JavaScript on the server. It’s built on the V8 JavaScript runtime and written in C++ — so it’s fast. Originally, it was intended as a server environment for applications, but developers started using it to create tools to aid them in local task automation. Since then, a whole new ecosystem of Node-based tools (such as Grunt, Gulp and webpack) has evolved to transform the face of front-end development.
To make use of these tools (or packages) in Node.js, we need to be able to install and manage them in a useful way. This is where npm, the Node package manager, comes in. It installs the packages you want to use and provides a useful interface to work with them.
In this guide, we're going to look at the basics of working with npm. We'll show you how to install packages in local and global mode, as well as delete, update and install a certain version of a package. We’ll also show you how to work with package.json to manage a project’s dependencies. If you’re more of a video person, why not sign up for SitePoint Premium and watch our free screencast: What is npm and How Can I Use It?
But before we can start using npm, we first have to install Node.js on our system. Let’s do that now.
Installing Node.js
Head to the Node.js download page and grab the version you need. There are Windows and Mac installers available, as well as pre-compiled Linux binaries and source code. For Linux, you can also install Node via the package manager, as outlined here.
For this tutorial, we’re going to use v12.15.0. At the time of writing, this is the current Long Term Support (LTS) version of Node.
Tip: You might also consider installing Node using a version manager. This negates the permissions issue raised in the next section.
Let’s see where node was installed and check the version:
$ which node /usr/bin/node $ node --version v12.15.0
To verify that your installation was successful, let’s give Node’s REPL a try:
$ node > console.log('Node is running'); Node is running > .help .break Sometimes you get stuck, this gets you out .clear Alias for .break .editor Enter editor mode .exit Exit the repl .help Print this help message .load Load JS from a file into the REPL session .save Save all evaluated commands in this REPL session to a file Press ^C to abort current expression, ^D to exit the repl
The Node.js installation worked, so we can now focus our attention on npm, which was included in the install:
$ which npm /usr/bin/npm $ npm --version 6.13.7
Updating npm
npm, which originally stood for Node Package Manager, is a separate project from Node.js. It tends to be updated more frequently. You can check the latest available npm version on this page. If you realize you have an older version, you can update as follows.
For Linux and Mac users, use the following command:
npm install -g npm@latest
For Windows users, the process might be slightly more complicated. This is what it says on the project's home page:
Many improvements for Windows users have been made in npm 3 - you will have a better experience if you run a recent version of npm. To upgrade, either use Microsoft's upgrade tool, download a new version of Node, or follow the Windows upgrade instructions in the Installing/upgrading npm post.
For most users, the upgrade tool will be the best bet. To use it, you’ll need to open PowerShell as administrator and execute the following command:
Set-ExecutionPolicy Unrestricted -Scope CurrentUser -Force
This will ensure you can execute scripts on your system. Next, you’ll need to install the npm-windows-upgrade tool. After you’ve installed the tool, you need to run it so that it can update npm for you. Do all this within the elevated PowerShell console:
npm install --global --production npm-windows-upgrade npm-windows-upgrade --npm-version latest
Node Packaged Modules
npm can install packages in local or global mode. In local mode, it installs the package in a node_modules folder in your parent working directory. This location is owned by the current user.
If you’re not using a version manager (which you probably should be), global packages are installed in {prefix}/lib/node_modules/, which is owned by root (where {prefix} is usually /usr/ or /usr/local). This means you would have to use sudo to install packages globally, which could cause permission errors when resolving third-party dependencies, as well as being a security concern.
Let’s change that!

Time to manage those packages
Changing the Location of Global Packages
Let’s see what output npm config gives us:
$ npm config list ; cli configs metrics-registry = "https://registry.npmjs.org/" scope = "" user-agent = "npm/6.13.7 node/v12.15.0 linux x64" ; node bin location = /usr/bin/nodejs ; cwd = /home/sitepoint ; HOME = /home/sitepoint ; "npm config ls -l" to show all defaults.
This gives us information about our install. For now, it’s important to get the current global location:
$ npm config get prefix /usr
This is the prefix we want to change, in order to install global packages in our home directory. To do that create a new directory in your home folder:
$ cd ~ && mkdir .node_modules_global $ npm config set prefix=$HOME/.node_modules_global
With this simple configuration change, we’ve altered the location to which global Node packages are installed. This also creates a .npmrc file in our home directory:
$ npm config get prefix /home/sitepoint/.node_modules_global $ cat .npmrc prefix=/home/sitepoint/.node_modules_global
We still have npm installed in a location owned by root. But because we changed our global package location, we can take advantage of that. We need to install npm again, but this time in the new, user-owned location. This will also install the latest version of npm:
npm install npm@latest -g
Finally, we need to add .node_modules_global/bin to our $PATH environment variable, so that we can run global packages from the command line. Do this by appending the following line to your .profile, .bash_profileor .bashrc and restarting your terminal:
export PATH="$HOME/.node_modules_global/bin:$PATH"
Now our .node_modules_global/bin will be found first and the correct version of npm will be used:
$ which npm /home/sitepoint/.node_modules_global/bin/npm $ npm --version 6.13.7
Tip: you can avoid all of this if you use a Node version manager. Check out this tutorial to find out how: Installing Multiple Versions of Node.js Using nvm.
Installing Packages in Global Mode
At the moment, we only have one package installed globally — the npm package itself. So let’s change that and install UglifyJS (a JavaScript minification tool). We use the --global flag, but this can be abbreviated to -g:
$ npm install uglify-js --global /home/sitepoint/.node_modules_global/bin/uglifyjs -> /home/sitepoint/.node_modules_global/lib/node_modules/uglify-js/bin/uglifyjs + [email protected] added 3 packages from 38 contributors in 0.259s
As you can see from the output, additional packages are installed. These are UglifyJS’s dependencies.
Listing Global Packages
We can list the global packages we've installed with the npm list command:
$ npm list --global home/sitepoint/.node_modules_global/lib ├─┬ [email protected] │ ├── [email protected] │ ├── [email protected] │ ├── [email protected] │ ├── [email protected] │ ├── [email protected] .................... ���─┬ [email protected] ├── [email protected] └── [email protected]
The output, however, is rather verbose. We can change that with the --depth=0 option:
$ npm list -g --depth=0 /home/sitepoint/.node_modules_global/lib ├── [email protected] └── [email protected]
That’s better; now we see just the packages we’ve installed along with their version numbers.
Any packages installed globally will become available from the command line. For example, here’s how you would use the Uglify package to minify example.js into example.min.js:
$ uglifyjs example.js -o example.min.js
Installing Packages in Local Mode
When you install packages locally, you normally do so using a package.json file. Let’s go ahead and create one:
$ mkdir project && cd project $ npm init package name: (project) version: (1.0.0) description: Demo of package.json entry point: (index.js) test command: git repository: keywords: author: license: (ISC)
Press Return to accept the defaults, then press it again to confirm your choices. This will create a package.json file at the root of the project:
{ "name": "project", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC" }
Tip: If you want a quicker way to generate a package.json file use npm init --y.
The fields are hopefully pretty self-explanatory, with the exception of main and scripts. The main field is the primary entry point to your program, and the scripts field lets you specify script commands that are run at various times in the life cycle of your package. We can leave these as they are for now, but if you’d like to find out more, see the package.json documentation on npm and this article on using npm as a build tool.
Now let’s try and install Underscore:
$ npm install underscore npm notice created a lockfile as package-lock.json. You should commit this file. npm WARN [email protected] No repository field. + [email protected] added 1 package from 1 contributor and audited 1 package in 0.412s found 0 vulnerabilities
Note that a lockfile is created. We’ll be coming back to this later.
Now if we have a look in package.json, we’ll see that a dependencies field has been added:
{ ... "dependencies": { "underscore": "^1.9.2" } }
The post A Beginner’s Guide to npm, the Node Package Manager appeared first on SitePoint.
by Michael Wanyoike via SitePoint https://ift.tt/2Q0Ku7Y
0 notes
Text
Build and Understand a Simple Node.js Website with User Authentication
Building websites with user authentication and management (login, registration, password reset, etc.), can be a huge pain. As a developer there are a million little things you need to worry about:
Storing the users in your database
Making sure you have the right user attributes defined
Forcing users to be logged in to view a page
Building registration and login forms
Creating password reset workflows that email users a link
Verifying new users when they sign up via email
Etc…
The list goes on and on.
Today I'm not only going to show you how to quickly build a Node.js website that supports all those things above, I'm going to teach you exactly what's going on behind the scenes so you fully understand how web authentication works.
If you've ever been curious about how web authentication and user security works, you will enjoy this. =)
What We're Building
As I mentioned above, today we'll be building a simple Node.js site that supports a few key user flows:
User registration
User login
Password reset
Email verification
The end product of this article looks like this:
If you want to see a preview of this project live, you can do so here: https://okta-express-login-portal.herokuapp.com/.
The site will be built using a few different tools (you don't need to know them already):
Express.js, the most popular web framework in the Node.js ecosystem.
express-session, a popular session management library. This is what will allow us to create and store cookies that remember who a user is.
Pug, a popular templating language that makes writing HTML a bit simpler.
oidc-middleware, a popular developer library that makes handling authentication using the OpenID Connect protocol simple
Install the Tools
The first thing you need to do is install all the open source tools we'll be using to build this Node.js site.
PS: If you don't already have Node.js setup and working on your computer, you can go checkout this link which shows you the best way to get it working regardless of what operating system you're using.
Next, install the express-generator tool, which is the officially supported bootstrapping tool for quickly getting started with Express.js.
npm install [email protected]
Once that's done, you'll want to scaffold your new Express.js site using express-generator.
express --view pug login-portal cd login-portal npm install
You now have a simple Express.js website that you can run and test out. Start up your new web server by running npm start then go visit http://localhost:3000 in your browser to make sure everything is working OK. If all is well, you should see a page like the one below.
Next, install some additional packages. We'll use these packages through the rest of the tutorial. Getting them installed and out of the way upfront will make it simpler later on.
To install all the extra dependencies, run the following commands in your terminal.
npm install [email protected] npm install @okta/[email protected] npm install @okta/[email protected]
Now, on with the show!
Setup Your Authorization Server
Historically, implementing web authentication has been a bit of a mess. Everyone used to implement authentication patterns in different, arbitrary ways. Over the last few years, however, the game has changed quite a bit with the introduction and growing popularity of the OpenID Connect protocol. If you want to read up on OpenID Connect, I recommend [this series]](https://developer.okta.com/blog/2017/07/25/oidc-primer-part-1).
One of the core tenants of OpenID Connect is the authorization server. An authorization server is a one-stop shop that handles all of the user login flows for your applications. The idea is that your application redirects to the authorization server to process user logins and the authorization server then redirects the user back to your website once the user has been authenticated.
Authorization servers make handling user management a significantly simpler, less risky task — so that's what we'll be doing today: using an authorization server provider (Okta) to make the process simple and secure.
Okta is free to use and allows you to create and manage users, authorization servers, and lots of other tasks that make handling web authentication simple.
To get started with the authorization server setup, you first need to go create a free Okta developer account: https://developer.okta.com/signup/. Once you've created your account and logged in, follow the steps below configure Okta and then you'll be ready to write some code!
Step 1: Store Your Org URL
The first thing you need to do is copy down the Org URL from the top-right portion of your Okta dashboard page. This URL will be used to route to your authorization server, communicate with it, and much more. You'll need this value later, so don't forget it.
Step 2: Create an OpenID Connect Application
Okta allows you to store and manage users for multiple applications you might be creating. This means that before we can go any further, you need to create a new OpenID Connect application for this project.
Applications in OpenID Connect have a username and password (referred to as a client ID and client secret) that allow your authorization server to recognize which application is talking to it at any given time.
To create a new application browse to the Applications tab and click Add Application.
Next, click the Web platform option (since this project is a web app).
On the settings page, enter the following values:
Name: login-portal
Base URIs: http://localhost:3000
Login redirect URIs: http://localhost:3000/users/callback
You can leave all the other values unchanged.
Now that your application has been created, copy down the Client ID and Client secret values on the following page, you'll need them later when we start writing code.
Step 3: Create an Authentication Token
In order to access the Okta APIs and be able to manage your user accounts with a great deal of granularity, you'll also need to create an Okta authentication token. This is an API key that will be used later on communicate with the Okta APIs and allows you to do things like:
Create, update, and delete users
Create, update, and delete groups
Manage application settings
Etc.
To create an authentication token click the API tab at the top of the page followed by the Create Token button. Give your token a name, preferably the same name as your application, then click Create Token. Once your token has been created, copy down the token value as you will need it later.
Step 4: Enable User Registration
The last piece of setup you need to complete is to enable user registration functionality for the authorization server. Normally, authorization servers only support login, logout, and stuff like that. But Okta's authorization server also supports self-service registration, so that users can create accounts, log into them, reset passwords, and basically do everything without you writing any code for it.
In your Okta dashboard, you'll notice a small button labeled < > Developer Console at the top-left of your page. Hover over that button and select the Classic UI menu option that appears.
Next, hover over the Directory tab at the top of the page then select the Self-Service Registration menu item. On this page click the Enable Registration button.
On the configuration page, leave all the settings as their default values, except for the Default redirect option. For this option, click the Custom URL radiobox and enter http://localhost:3000/dashboard as the value.
This setting essentially tells the authorization server where to redirect users after they've successfully created a new account on your site.
Once you've clicked Save, the last thing you need to is switch back to the developer console.
Hover over the Classic UI button at the top right of the page and select the < > Developer Console menu item from the dropdown.
Configure Session Management
Now that all the setup work is done, let's write some code!
The first thing we'll add to this basic Express.js site is support for sessions using the express-session library.
Session management is the core of any authentication system. It's what allows a user to stay logged into your site and not have to re-enter their credentials before viewing each page. The most secure way to handle user sessions is via server-side cookies, which is why we'll be using the express-session library: it allows us to create and manage server-side cookies.
To start, open up the ./app.js file in your favorite editor (I prefer neovim), and import the session library at the top of the file alongside the other import statements. The app.js file is the heart of your Express.js site. It initializes the Express.js web server, contains the site settings, etc.
var createError = require('http-errors'); var express = require('express'); var path = require('path'); var cookieParser = require('cookie-parser'); var logger = require('morgan'); var session = require("express-session");
Next, you need to remove the cookie-parser library that express-generator included by default, since we won't be using it. In the ./app.js file delete the following two lines of code.
var cookieParser = require('cookie-parser'); // and… app.use(cookieParser());
Now all you need to do is plug the express-session library into the ./app.js file along with the other middlewares.
app.use(logger('dev')); app.use(express.json()); app.use(express.urlencoded({ extended: false })); app.use(cookieParser()); app.use(express.static(path.join(__dirname, 'public'))); app.use(session({ secret: 'LONG_RANDOM_STRING_HERE', resave: true, saveUninitialized: false }));
Make sure to replace LONG_RANDOM_STRING_HERE with an actual random string you type. This string is what will keep your user's cookies safe from compromise. I personally like to bash my hands around on the keyboard for a second to generate something random.
This session library handles a lot of work behind the scenes:
It creates secure, cryptographically signed cookies so you can store data in a user's browser. Cryptographic signing is a technique that allows your server to tell whether or not a user has tried to "modify" their cookies to make it look as if they're someone they're not.
It gives you a simple API for creating and removing cookies
It allows you to tweak and configure cookie settings based on what you need to do
As you'll see in a moment, this library is used by the oidc-middleware library behind the scenes to make user authentication magical.
Create Express.js Views
The next thing we're going to do is create our Express.js views. Views in Express.js are nothing more than HTML templates (web pages) that we want to display to a user. But unlike normal HTML, we'll be using the Pug templating language to create our views.
Pug is one of the most popular templating languages in the Node.js ecosystem because it allows you more concisely write HTML, use variables, and things like that.
Create the Layout View
The first (and most important!) view we're going to create is the ./views/layout.pug view. This is the "base" view that all our other views will extend.
In this view we'll define the basic layout of all the pages, the navbar, and stuff like that. Open up the ./views/layout.pug and replace whatever is in the file with the following.
block variables doctype html html(lang="en") head meta(charset="utf-8") meta(name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no") link(rel="stylesheet" href="https://feeds.feedblitz.com/~/t/0/0/scotch_io/~https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous") link(rel="stylesheet", href="https://feeds.feedblitz.com/~/t/0/0/scotch_io/~scotch.io/stylesheets/style.css") title okta-express-login-portal: #{title} body div.top-bar.d-flex.flex-column.flex-md-row.align-items-center.p-3.px-md-4.mb-3.bg-white.border-bottom.box-shadow h5.my-0.mr-md-auto.font-weight-normal a(href="https://feeds.feedblitz.com/~/t/0/0/scotch_io/~scotch.io/", title="Expresso") okta-express-login-portal nav.my-2.my-md-0.mr-md-3 a.p-2.text-dark(href="https://feeds.feedblitz.com/~/t/0/0/scotch_io/~scotch.io/", title="Home") Home if user == undefined a.p-2.text-dark(href="https://feeds.feedblitz.com/~/t/0/0/scotch_io/~scotch.io/users/login") Log In / Register else a.p-2.text-dark(href="https://feeds.feedblitz.com/~/t/0/0/scotch_io/~scotch.io/dashboard") Dashboard a.p-2.text-dark(href="https://feeds.feedblitz.com/~/t/0/0/scotch_io/~scotch.io/users/logout") Logout .container block content footer. Built with #[a(href="https://feeds.feedblitz.com/~/t/0/0/scotch_io/~https://expressjs.com/") Express.js], login powered by #[a(href="https://feeds.feedblitz.com/~/t/0/0/scotch_io/~https://developer.okta.com/") Okta].
As you can probably figure out if you're at all familiar with HTML, pug is very similar to HTML but uses whitespace instead of closing tags (like the Python programming language).
This layout view doesn't do anything except render a simple page with a navbar at the top, a footer at the bottom, and two special constructs, block variables and block content.
The block variables line at the top of the file means that any of the templates that inherit from this one will be able to inject some variables into the page. You might have noticed that the title tag contains a variable: #{title} — this is one of the variables that a child template can overwrite later on.
Did you notice the block content line right above the footer? This block allows a child template to inject HTML into our layout template at just the right spot — this way our child templates don't need to re-define a navbar, page header, etc.
By using these two blocks: variables and content, our child templates can build full web pages with nothing more than a title and some body content. Pretty nifty.
Create the Homepage View
The next view we'll create is the ./views/index.pug view. Open that file and insert the following code.
extends layout block variables - var title = "Home" block content h2.text-center Express App .row .offset-sm-2.col-sm-8 .jumbotron.text-center. Welcome to your new Express app! Please visit the #[a(href="https://feeds.feedblitz.com/~/t/0/0/scotch_io/~https://github.com/rdegges/okta-express-login-portal", title="okkta-express-login-portal on GitHub") GitHub page] to learn more.
Notice the extends layout line at the top. This is what tells pug that this template is a child of the layout template we created earlier.
In the block variables section we then define our title variable which will be used in the layout template to output the page title, and in the block content section we insert the HTML for the rest of the page.
As you can hopefully see by now, template inheritance in Pug is pretty straightforward.
Create the Dashboard View
The next view to create is the dashboard view. This is the page users will see once they've logged into the site. Open up the ./views/dashboard.pug file and insert the following code.
extends layout block variables - var title = "Dashboard" block content h2.text-center Dashboard .row .offset-sm-2.col-sm-8 .jumbotron.text-center. Welcome to your dashboard page, #{user.profile.firstName}.
You'll notice that in this template there's a new variable being used: #{user}. This will eventually refer to the currently logged in user as you'll see later on.
Create the Error Views
The last two views you need to create are for handling errors.
Open up the ./views/error.pug view and insert the following code.
extends layout block content h1= message h2= error.status pre #{error.stack}
This view will be rendered when the user hits a URL that doesn't exist (404), or when the web server has a problem (5XX).
You'll also need to create a file named ./views/unauthenticated.pug and insert the following code. This view will be displayed to a user if they visit a page that requires them to be logged in.
extends layout block variables - var title = "Unauthenticated" block content h2.text-center You Must Log In to View This Page p.text-center. You must be signed in to view this page. Please #[a(href="https://feeds.feedblitz.com/~/t/0/0/scotch_io/~scotch.io/users/login", title="Login") login or register] to view this page.
Create Public Routes
Routes in Express.js are the place where you define application logic. They dictate what code runs when a particular URL is hit by a user, and what response is sent back.
To get started, let's remove the default routes that express-generator created for you. Run the following command to remove them.
rm routes/*
Next, create a file named ./routes/public.js and insert the following code.
const express = require("express"); const router = express.Router(); // Home page router.get("/", (req, res) => { res.render("index"); }); module.exports = router;
In this module we're creating a new Express.js Router and telling it that if a user makes a GET request to the / URL, then we're going to run a function that renders the index.pug view file we created earlier and returns it to the user.
Now this won't take effect just yet (for reasons you'll learn about later on), but once this router is "enabled", every time a user makes a request for the homepage of the site, eg: http://localhost:3000, this code will run and the index.pug view will be shown.
Pretty neat, right?
Next, create a file named ./routes/dashboard.js and insert the following code.
const express = require("express"); const router = express.Router(); // Display the dashboard page router.get("/", (req, res) => { res.render("dashboard"); }); module.exports = router;
This router acts similarly to the homepage router above, except it is rendering our dashboard page. While it doesn't make sense just yet, if a user eventually visits the /dashboard URL, this function will run which will render the dashboard.pug defined earlier.
If you were to go into this file and define another route, for example:
router.get("/test", (req, res) => { res.render("test"); });
… You would find that a user would need to visit /dashboard/test to trigger the function to run. Again: don't worry about this not adding up just yet, we'll get to that down below.
Enable the Routes
Now that you've created some routes for public pages, let's enable them with Express.js so we can actually see them in action!
To do this, open up the ./app.js file and delete the following two lines.
var indexRouter = require('./routes/index'); var usersRouter = require('./routes/users');
Replace those two lines with the two lines of code below.
const dashboardRouter = require("./routes/dashboard"); const publicRouter = require("./routes/public");
Now we're importing the correct route files we just defined above.
Next, scroll down until you see the following two lines of code and delete them.
app.use('/', indexRouter); app.use('/users', usersRouter);
Those lines of code were loading up the old routes we just deleted. Now you need to change those lines of code to look like this.
app.use('/', publicRouter); app.use('/dashboard', dashboardRouter);
Is it starting to make sense now? These app.use lines of code tell Express.js that if a user visits the / URL, it should look into the ./routes/public.js file and start matching URLs there to run against. So if a user visits the homepage, eg: /, Express.js will look in the ./routes/public.js file, find the route that serves the / URL, then run the associated function.
The same thing happens with the dashboardRouter below. If a user visits /dashboard, then Express.js will look in the ./routes/dashboard.js file for a function that runs when the / URL is called, because /dashboard + / is the path the user is visiting!
Routes in Express.js make it easy to compose complex sites with lots of nested URLs without a lot of work.
Now that you've enabled your routes, go test them out. Start your web server by running the command below.
npm start
Then visit http://localhost:3000 in your browser. You should see the following page rendered.
NOTE: This page doesn't look just right yet because we haven't created any CSS yet. We'll do that last.
If you now go visit the dashboard page you created, http://localhost:3000/dashboard, you'll notice you get an error. That is because that Pug view refers to the #{user} variable we haven't yet defined. We'll get to that soon.
Configure User Authentication
Now that our Express.js site is starting to become functional, let's dive deeper into user authentication.
The first thing you need to do is open up ./app.js and import the following two libraries at the top of the file.
var createError = require('http-errors'); var express = require('express'); var path = require('path'); var cookieParser = require('cookie-parser'); var logger = require('morgan'); var session = require('express-session'); var okta = require("@okta/okta-sdk-nodejs"); var ExpressOIDC = require("@okta/oidc-middleware").ExpressOIDC;
The two libraries we just added are at the bottom of the list: @okta/okta-sdk-nodejs and @okta/oidc-middleware. These two libraries handle all of the OpenID Connect communication and routing.
The next thing we need to do is create an oktaClient object as well as an ExpressOIDC object. These will be used in a moment once we've configured them and given them the right credentials.
To do this, open up your ./app.js file again, find the line that reads var app = express();, and insert the following code immediately beneath it.
var oktaClient = new okta.Client({ orgUrl: '{yourOktaOrgUrl}', token: '{yourOktaToken}' }); const oidc = new ExpressOIDC({ issuer: "{yourOktaOrgUrl}/oauth2/default", client_id: {yourClientId}, client_secret: {yourClientSecret}, redirect_uri: 'http://localhost:3000/users/callback', scope: "openid profile", routes: { login: { path: "/users/login" }, callback: { path: "/users/callback", defaultRedirect: "/dashboard" } } });
Now, remember those values I told you to write down way back at the beginning of this post? Now you need them! Make sure you substitute out the following variables above for the proper values: {yourOktaOrgUrl}, {yourOktaToken}, {yourClientId}, and {yourClientSecret}.
The oidc object created handles 100% of the OpenID Connect protocol support. It handles router the users to the authorization server to handle user registration, login, password reset, etc. It handles logging the users into your application using secure cookies (powered by express-session), and it also handles everything else.
The oktaClient object is merely used to retrieve user data from the Okta API service.
Now that our OpenID Connect support is ready to be used, let's enable it. To do this, open up the ./app.js and find the session middleware from earlier, then add the following line beneath it.
app.use(session({ secret: 'asdf;lkjh3lkjh235l23h5l235kjh', resave: true, saveUninitialized: false })); app.use(oidc.router);
The app.use(oidc.router); call is all that's needed to tell Express.js to enable the routes that ship with the oidc-middleware library to handle all of the OpenID Connect support. You might have noticed above that when we created the oidc object we specified some routes in the configuration. These settings dictate what URLs we want to use to handle user login, and what URLs we want to redirect users to after they've been logged in.
One benefit of this router being enabled is that from this point forward, in any of our route code, we'll have access to a special variable, req.userinfo, which contains some of the currently logged in user's basic profile information (pulled from Okta).
And while req.userinfo is nice, it'd be a lot nicer if we could get any data about the currently logged in user that we want.
So let's go ahead and define another middleware to help us with that. Immediately below the app.use(oidc.router); code, insert the following:
app.use((req, res, next) => { if (!req.userinfo) { return next(); } oktaClient.getUser(req.userinfo.sub) .then(user => { req.user = user; res.locals.user = user; next(); }).catch(err => { next(err); }); });
This middleware will run on every user request, and does the following:
It checks to see if there is a currently logged in user or not by looking at the req.userinfo object. If there is no user logged in, it will do nothing (return next();).
If there IS a user logged in, this middleware will then use the Okta Node SDK library to retrieve the user object from the Okta API.
Finally, it will create two new values: req.user and res.locals.user which point to the user object directly.
This means that in any route we define later on, we could access the req.user object directly to view the user's information, edit it, or even delete it.
For example, you could create the following route below to display the user's profile information each time a user visits the /test URL:
app.get('/test', (req, res) => { res.json({ profile: req.user ? req.user.profile : null }); });
Let's also go ahead and create one additional middleware, loginRequired, that will only allow a user to visit a route if they've been logged in already. This will come in handy if you want to build pages that only logged in users can access (a dashboard, etc.).
Below the code above, go ahead and define the function below.
function loginRequired(req, res, next) { if (!req.user) { return res.status(401).render("unauthenticated"); } next(); }
Since we want to ensure only logged in users can view our dashboard page, let's also go back and modify our route code for the dashboard.
Find the line of code that enabled the dashboard route in your ./app.js.
app.use('/dashboard', dashboardRouter);
Now modify it to look like this.
app.use('/dashboard', loginRequired, dashboardRouter);
By injecting the loginRequired function immediately after the URL pattern, Express.js will first run our loginRequired middleware BEFORE the dashboardRouter is processed. This way, if a user visits any page that starts with the URL /dashboard they'll be required to log in before they can access it!
The final thing we need to do to finish up our authentication component is define a logout route. The oidc-middleware library provides logout functionality, but doesn't automatically generate a route for it.
To do this, create a new file named ./routes/users.js and put the following code inside of it.
const express = require("express"); const router = express.Router(); // Log a user out router.get("/logout", (req, res) => { req.logout(); res.redirect("/"); }); module.exports = router;
As you can probably tell, this route will log a user out of their account if they send a POST request to the /users/logout URL. The only thing we need to do now is enable this route in our ./app.js.
Open up ./app.js, and import this new route file alongside the others at the top of the file.
const dashboardRouter = require("./routes/dashboard"); const publicRouter = require("./routes/public"); const usersRouter = require("./routes/users");
Next, scroll down until you see your other routers being enabled, and enable this router as well.
app.use('/', publicRouter); app.use('/dashboard', loginRequired, dashboardRouter); app.use('/users', usersRouter);
Congratulations, you've now got user management and authentication fully configured for your website! And you didn't even have to write any code, manage any passwords, store anything in a database, etc!
How Authentication Works
Now that you've seen how to successfully setup authentication for your Node.js websites, let's talk a bit more about how it works and explore the full authentication flow.
In order to explain each component, let's assume that you're visiting this website and are not currently logged into your account.
When you first click the Log In / Register button at the top of the page, the oidc-middleware library is going to redirect you to an Okta hosted domain (the authorization server). Here's the sort of URL you'll be redirected to:
https://dev-842917.oktapreview.com/login/login.htm?fromURI=/oauth2/v1/authorize/redirect?okta_key=qBpZVCpQIJlxUALtybnI9oajmFSOmWJNKL9pDpGtZRU
NOTE: You can fully customize this domain name, look, and feel using Okta.
Once you've landed on the authorization server page, you can either enter your account credentials and login immediately or create a new account. This functionality is handled by the authorization server completely.
If you enter your credentials and click the Sign In button on the authorization server, what happens behind the scenes is:
Your password is hashed and your credentials are checked against the Okta user database to determine whether or not they are correct
If your credentials are correct, a new session cookie is created for you on the Okta hosted domain (eg: dev-842917.oktapreview.com, in this case), and you are redirected to the redirect_uri setting you provided earlier when defining the ExpressOIDC object. In this case, you'd be redirected to http://localhost:3000/users/callback. When you're redirected to this URL, the authorization server will also pass along a special code token. This is part of the OpenID Connect Authorization Code flow.
Your Express.js app will receive the request to /users/callback and service the request automatically using the oidc-middleware library's built-in routes. The route servicing this URL will intercept the request and exchange the code token for an access and id token. This process of exchanging the code token is part of the OpenID Connect authorization code flow and is detailed more here: https://developer.okta.com/authentication-guide/implementing-authentication/auth-code#3-exchanging-the-code-for-tokens.
Once these tokens have been retrieved, the oidc-middleware library takes the user's basic information embedded in the id token and stores it in a session cookie.
Then, the oidc-middleware library redirects you to the dashboard page as a fully logged-in user.
From this point on, each time your browser makes a request to the Express.js website, the cookie containing your profile information will be sent back to Express.js, so that the oidc-middleware library can recognize who you are and populate a req.userinfo object with your account data.
Once your session cookies have expired (or have been wiped via a logout procedure), the process starts all over again.
Create Styles
I'm not a professional designer, but even I can make this website look a little better.
Create a file named ./public/stylesheets/style.css and put the following CSS into it.
.top-bar a { text-decoration: none; color: inherit; } footer { border-top: 1px solid rgba(0,0,0,.1); margin-top: 4em !important; padding-top: 1em; text-align: center; margin-top: 1em; } h2 { margin-bottom: 2em; } .container { padding-top: 2em; }
This will make the page styles look a little nicer.
Test Out Your New Login Portal
Now that your Express.js website is built, why not take it for a test drive? Start up your web server by running the npm start command, visit http://localhost:3000, and test things out!
You'll notice a few things:
If you click the Log In / Register button at the top of the page, you can either create a new user account OR log into an existing one. This functionality is all provided by Okta's authorization server automatically.
Once you're logged in, you'll be redirected to the /dashboard page, which will greet you by your first name. Remember that #{user.profile.firstName} variable in the ./views/dashboard.pug file earlier? That variable is now you actual user account since you've now plugged in all the appropriate middleware.
If you log out, then immediately click the Log In / Register button again, you'll be instantly logged in without needing to re-enter your username and password. This is a feature of OpenID Connect — the authorization server remembers who you are for a set amount of time. This is the same way that Google Login and Facebook Login work!
If you're already logged into your Okta account and instantly get logged into the dashboard, don't worry. Just open a new incognito window in your browser and go through the flow there.
Learn More About Node.js and Authentication
I hope you enjoyed seeing how authentication works with OpenID Connect and Node.js. Building websites with user management can be a pain, but new protocols like OpenID Connect alongside providers like Okta make the process much simpler.
If you'd like to learn more about building web apps in Node, you might want to check out these other great posts:
Build Secure Node Authentication with Passport.js and OpenID Connect
Build User Registration with Node, React, and Okta
Simple Node Authentication
Build a Basic CRUD App with Vue.js and Node
Finally, please follow us on Twitter to find more great resources like this, request other topics for us to write about, and follow along with our new open source libraries and projects!
PS: If you liked this project and want to see the source code in one place, please go checkout and star the GitHub repository.
And… If you have any questions, please leave a comment below!
via Scotch.io https://ift.tt/2L26FJw
0 notes
Text
0.1.3 and 0.1.3b
Realized I never posted a changelog for 0.1.3 here! I also just put out 0.1.3b for windows. Have a combined changelog below!
New
New Class! The TINKERER!
New Items - Grenades
Robot Follower
Catacoins!
Custom Kids!
Battle music!
AC Forts!
Changes
0.1.3
Oog now have energy for the void amulet to drain
Changed some reputation requirements
Large mushrooms are now heavier and bounce away creatures even when not upright or when struck
Mushrooms are know knocked away by attacks
Improved Magic 101's charged tome attack
Improved Magical Combat's charged tome attack
As a Spellwright, projectiles from tome attacks will auto-aim
Undo is now removed from your skill grid when its max charges reach 0
Arrow types can be swapped by holding "Stow", even when having held/stown items
Made Anticropolis background details better and more unique
Added splash visual effect for entering water
Added bubble effect to lava surface
Changed explosion visual effect
Changed flame wave visual effect
Made icy slopes much more slippery
Holding left/right no longer reduces your speed if you're moving faster in the same direction
Added a V-Sync option in Graphics options
Setting V-Sync to "ALT" should help WIN 10 users with their black fullscreen issue but may
introduce other issues
Added option to disable contextual prompts in Graphics options
Some changes to lighting in the Anticropolis
Orb of Leveling light now cycles through colors
Classing up as a wanderer more dramatically increases farsight distance
Improved camera point of interest functionality
Doubled charged duration of Soul weapons and added a damage penalty for losing charge
Changed behavior of shadow strikers for Soul weapons
Stronger enemies generate more shadowbolt strikers when killed with soul weapons
Changed the behavior of lanterns to make them more useful
Lanterns now remove invisibility from lit enemies
Wearing sandals, going barefoot, or being naked in the anticropolis all increase heat loss
Sandals have less durability; Sandals/bare feet kick faster and increase freerun wall-run speed
Boots have higher durability, kick slower, and decrease freerun wall-run speed
Heavy weapons and equipment slow freerun wall-run startup time
Boots reduce damage from ground spikes 1 at the cost of durability
Helms and Coifs reduce damage from ceiling spikes by 1 at the cost of durability
Slightly reduced input window for heavy lifting creatures
Added learned percentage of weapon skill to "Likes [Weapon]" description
Increased shop security
Shops now come in different types
Shopkeepers offer different services based on their store type
Added living space to shops
Added background details to shops
Merchants will buy your items for closer to their actual value with higher LUC
Mixed potions now identify if their components are identified after being made
Weapons clashing gains the attention of nearby creatures
Disarming enemies while you have [Pilfer] now [steals their weapon]
Using Grapple on enemies now [disarms them] if you have [Disarm]
Made gamepad input for mighty stomp harder to do accidentally
Refined Air Dash behaviour
Improved input responsiveness for quickly throwing things after taking Trajectory or Deft Throw
Changed appearance of Trajectory throws
Trajectory now briefly slows time when initiated
Deft throw now has a slight auto-aim
Weapons thrown with trajectory only bounce once
Realized Amulet of the Void now only activates upon stealing energy/magic
Reduced Amulet of the Void's range
Increased INT requirement for enemy amulet use
Can now ride boulders
Can now initiate trajectory bow shots downward
Crush trap chain reeling sound is now emitted from the crushing head
Corpses are no longer valued by name length
Humanoid corpses' worth now take into account their equipped items
0.1.3b
Reduced Tinker-Bot max hp increase from class-up from +5 to +3 each
Classing to Engineer lets tinker-bot carry heavy items
Reduced Tinker-Bot stat increase when going from Mechanic to Engineer
Added option to tinker-bot to only pick up unusable objects
Added input prompts to tinkerbot's manual mode
Added input prompts to character select menu
Engineer's Tinkerbot changes sprite to reflect improvement
Tinkerbot repairs damage from poor repairs by descending floors
Headaches now last for 2 floors instead of 1
Tinker-bot is better at avoiding shifting platforms in the AC
Fixes
0.1.3
Fixed pools of water spawning incorrectly
Fixed amulets de-identifying when INT drops
Energy with Void Amulet drains one from max
Input icon for class ability doesn't display when using controller
Arrows behave a bit better in tight corridors
Crash when drinking Potion of Cleansing Flame
Icicles are fine in lava
Flame pipes add excessive "Charred"s to corpses
Teleport traps can spawn on the ghost and other "up-to-interact" features
Boulder traps don't trigger over too-short distances
Flame Wave, Infernus, and burning enemies don't properly produce light
Fixed a bug with disabling out-of-view instances
Interactable object title text is drawn in the wrong color
Burrah-boi meal doesn't work at all
Strange transparency artifacts with alphas while in fullscreen
Solidified Lava in reaper room is rendered incorrectly
Still climb up and down ladders while tracking/aiming lantern
Can heavy lift creatures while already holding an item
Heavy lifted creatures can be picked up by humanoids other than the one who initiated the heavy
lift
Ghost sometimes provides too many, too few, or incorrect trait options
All the music was in mono BECAUSE I'M AN IDIOT
Crash when ogo slime on feet explodes in a gas trap
Crash when losing one's weapon-arm mid-attack while using a bow
Potions are overly resource-intensive
Firing a bow homes in on switches even when they're behind you
Missing particle effect upon level up
Breathing Masks don't work
NB becomes unresponsive after being blocked or shield parried
Using raise dead on a player in co-op doesn't restore their charge stars
Dead things gain value as they degrade
0.1.3b
Undo isn't removed from the spell bar when maximum charges reach 0
Missing leg causes air dash to behave strangely
Orb blinks when intersecting walls even when carried by Tinkerbot
Barrels sometimes burn them forever
Can be moved while going through doors
Moving Platforms in the AC can overlap the entrance/exit doors
Bot hits self with thrown arrows
Bot weapons don't disintegrate when broken
Can give bots heavy objects through the idle menu
Likes/Good With [Weapon] doesn't specify weapon type when loading a template kid
Spellbooks stolen by rats become invisible
Reaper weapons fly away after unpausing from tinker mode switch
Spikes in reaper room float when walls disappear
Wind-up turtle can be poisoned
Thrown weapons not reflected by armor of reflection
Potions deal damage incorrectly
Can't change Tinkerbot mode in coop while the screen is split
Bear trap keeps you caught after Undo
If you ride a boulder into a wall, the boulder may push you slightly into it
Weakness and a few other status effects aren't reciprocated by reciprocity
Lava bridges sprite turns to wooden bridge sprite when crushed by crush traps
NB sometimes spawns in walls and other strange places
Tinkerbot mode cannot be changed when class ability is assigned to SPELL
Custom Kids can't start with amulets
"gml_Object_par_player_Step_0" crashes
Locked rooms often generate without treasure
Wooden barricades can block off areas
5 notes
·
View notes